import shutil
import numpy as np
import const
from utils import file_util, debug_util, image_processing

npy_suffix = '.npy'
txt_suffix = '.txt'

def get_face_embedding(stu_no, files_list):
    # 转换颜色空间RGB or BGR
    colorSpace = "RGB"
    embeddings = []  # 用于保存人脸特征数据库
    for image_path in files_list:
        debug_util.logger.debug("stuno: [%s] processing img: %s" % (stu_no, image_path))
        image = image_processing.read_image_gbk(image_path, colorSpace=colorSpace)
        # 进行人脸检测，获得bounding_box
        bboxes, landmarks = const.FACE_DETECT.detect_face(image)
        bboxes, landmarks = const.FACE_DETECT.get_square_bboxes(bboxes, landmarks, fixed="height")
        if bboxes == [] or landmarks == []:
            debug_util.logger.warning("stuno: [%s] img: %s no face" % (stu_no, image_path))
            continue
        if len(bboxes) >= 2 or len(landmarks) >= 2:
            debug_util.logger.info("stuno: [%s] img: %s have %d faces" % (stu_no, image_path, len(bboxes)))
            continue
        # 获得人脸区域
        face_images = image_processing.get_bboxes_image(image, bboxes, const.RESIZE_HEIGHT, const.RESIZE_WIDTH)
        # 人脸预处理，归一化
        face_images = image_processing.get_prewhiten_images(face_images, normalization=True)
        # 获得人脸特征
        pred_emb = const.FACE_NET.get_embedding(face_images)
        embeddings.append(pred_emb)
    return embeddings

def get_embedding_str_list(embeddings):
    embedding_str_list = list()
    for embedding in embeddings:
        line = ''
        for i in range(len(embedding[0])):
            if not i == len(embedding[0]) - 1:
                line = line + str(embedding[0][i]) + ','
            else:
                line = line + str(embedding[0][i])
        embedding_str_list.append(line.strip())
    return embedding_str_list

def create_embedding_file(stu_no, align_imgs_save_path):
    embedding_path = const.NPY_PATH + stu_no + '/'
    file_util.no_exist_and_create(embedding_path, align_imgs_save_path)
    npy_filename = stu_no + npy_suffix
    txt_filename = stu_no + txt_suffix
    npy_file_path = embedding_path + npy_filename
    txt_file_path = embedding_path + txt_filename
    file_util.delete_file(npy_file_path, txt_file_path)
    file_list = file_util.get_file_labels(align_imgs_save_path)
    embeddings = get_face_embedding(stu_no, file_list)
    debug_util.info('have {} image'.format(len(embeddings)))
    embeddings = np.asarray(embeddings)
    # save npy
    np.save(npy_file_path, embeddings)
    # save txt
    embedding_str_list = get_embedding_str_list(embeddings)
    with open(txt_file_path, 'a+') as f:
        for embedding_str in embedding_str_list:
            f.write(embedding_str + '\n')
    # delete the align imgs
    shutil.rmtree(align_imgs_save_path)
    return npy_filename, npy_file_path, txt_filename, txt_file_path

def compare_embedding(username, pred_emb, dataset_emb):
    pred_num = len(pred_emb)
    dataset_num = len(dataset_emb)
    pred_name = []
    pred_score = []
    for i in range(pred_num):
        dist_list = []
        for j in range(dataset_num):
            dist = np.sqrt(np.sum(np.square(np.subtract(pred_emb[i, :], dataset_emb[j, :]))))  # 计算欧式距离
            dist_list.append(dist)
        min_value = min(dist_list)
        pred_score.append(min_value)
        if (min_value > const.THRESHOLD):  # 如果最小值大于阈值则判定不是同一人
            pred_name.append('unknow')
        else:
            pred_name.append(username)
    return pred_name, pred_score


